package com.vayne.lookupdemo;

import com.vayne.bean.Course;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.HierarchicalBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @author xuerui.zhang
 * @since 2020/4/9 下午1:36
 */
public class HierarchicalLookupDemo {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        applicationContext.register(HierarchicalLookupDemo.class);

        // 1、获取：HierarchicalBeanFactory <- ConfigurableBeanFactory <- ConfigurableListableBeanFactory
        ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory();
        // System.out.println("当前 Bean 是否含有 parent：" + beanFactory.getParentBeanFactory());

        // 2、设置 parent
        HierarchicalBeanFactory parentBeanFactory = createParentFactory();
        beanFactory.setParentBeanFactory(parentBeanFactory);
        // System.out.println("当前 Bean 是否含有 parent：" + beanFactory.getParentBeanFactory());

        displayContainsLocalBean(beanFactory, "course");
        displayContainsLocalBean(parentBeanFactory, "course");

        displayBeanContainsBean(beanFactory, "course");
        displayBeanContainsBean(parentBeanFactory, "course");

        Course course = BeanFactoryUtils.beanOfTypeIncludingAncestors(beanFactory, Course.class);

        // 启动应用上下文
        applicationContext.refresh();

        // 关闭
        applicationContext.close();
    }

    private static HierarchicalBeanFactory createParentFactory() {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        XmlBeanDefinitionReader beanDefinition = new XmlBeanDefinitionReader(beanFactory);
        String path = "classpath:/dependency_lookup_config.xml";
        beanDefinition.loadBeanDefinitions(path);
        return beanFactory;
    }

    private static void displayBeanContainsBean(HierarchicalBeanFactory beanFactory, String beanName) {
        System.out.printf("当前 BeanFactory【%s】是否包含 Local Bean【%s】: %s \n",
                beanFactory, beanName, containsBean(beanFactory, beanName));
    }

    private static boolean containsBean(HierarchicalBeanFactory beanFactory, String beanName) {
        BeanFactory parentBeanFactory = beanFactory.getParentBeanFactory();
        if (parentBeanFactory instanceof HierarchicalBeanFactory) {
            HierarchicalBeanFactory hierarchicalBeanFactory = (HierarchicalBeanFactory) parentBeanFactory;
            if (containsBean(hierarchicalBeanFactory, beanName)) {
                return true;
            }
        }
        return beanFactory.containsLocalBean(beanName);
    }

    private static void displayContainsLocalBean(HierarchicalBeanFactory beanFactory, String beanName) {
        System.out.printf("当前 BeanFactory【%s】是否包含 Local Bean【%s】: %s \n",
                beanFactory, beanName, beanFactory.containsLocalBean(beanName));
    }
}
